﻿using Microsoft.AspNetCore.Authorization;
using System.Globalization;
using System.Net;
using System.Security.Claims;

namespace CustomAuthorization.MinimumAgeAuthorize
{
    public class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeAuthorizeAttribute>
    {
        private readonly ILogger<MinimumAgeAuthorizationHandler> _logger;

        public MinimumAgeAuthorizationHandler(ILogger<MinimumAgeAuthorizationHandler> logger)
        {
            _logger = logger;
        }
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MinimumAgeAuthorizeAttribute requirement)
        {
            // Log as a warning so that it's very clear in sample output which          authorization
            // policies(and requirements/handlers) are in use.
            _logger.LogWarning("Evaluating authorization requirement for age >={ age}", requirement.MinimumAge);
            var dateOfBirthClaim = context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth);
            if (dateOfBirthClaim != null)
            {
                var dateOfBirth = Convert.ToDateTime(dateOfBirthClaim.Value,CultureInfo.InvariantCulture);
                var age = DateTime.Today.Year - dateOfBirth.Year;
                if (dateOfBirth > DateTime.Today.AddYears(-age))
                {
                    age--;
                }
                if (age >= requirement.MinimumAge)
                {
                    _logger.LogInformation("Minimum age requirement satisfied. User is { age } years old.", age);
                    context.Succeed(requirement);
                }
                else
                {
                    _logger.LogWarning("Current User's DateOfBirth claim ({DateOfBirth}) does not satisfy the minimum age authorization requirement {age}",dateOfBirthClaim.Value,requirement.MinimumAge);
                    //context.Fail();
                }
            }
            else
            {
                _logger.LogInformation("No DateOfBirth Claim present");
            }
            return Task.CompletedTask;
        }
    }
}
